home *** CD-ROM | disk | FTP | other *** search
/ QuickTime 2.0 Developer Kit / QuickTime 2.0 Developer Kit.iso / pc / windows / qtw_201 / setup / samples / mmio_dh / mmio_dh.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-19  |  38.5 KB  |  1,396 lines

  1. /*
  2. ********************************************************************************
  3. **
  4. ** File: datah.cpp
  5. **
  6. ** Description:
  7. **
  8. **  Set tab stops to 4.
  9. **
  10. **  Data Handler component for QuickTime for Windows.
  11. **
  12. ** Routines:
  13. **
  14. **  Routines enclosed in [brackets] exist, but are unsupported.
  15. **
  16. **  DataHOpen();                        - component manager open call
  17. **  DataHClose();                       - component manager close call
  18. **  DataHCanDo();                       - component manager cando call
  19. **  DataHVersion();                     - component manager version call
  20. **  DataHGetData();                     - immediate data read
  21. **  [DataHPutData();]                   - data write
  22. **  [DataHFlushData();]                 - flush write buffers
  23. **  [DataHOpenForWrite();]              - open for write access
  24. **  [DataHCloseForWrite();]             - close for write access
  25. **  DataHOpenForRead();                 - open for read access
  26. **  DataHCloseForRead();                - close for read access
  27. **  DataHSetDataRef();                  - set data reference
  28. **  DataHGetDataRef();                  - get data reference
  29. **  DataHCompareDataRef();              - compare data references
  30. **  DataHTask();                        - provide background time
  31. **  DataHScheduleData();                - schedule advance read
  32. **  DataHFinishData();                  - complete scheduled reads
  33. **  DataHFlushCache();                  - flush cache buffers
  34. **  DataHResolveDataRef();              - resolve data reference
  35. **  DataHGetFileSize();                 - return file size
  36. **  DataHCanUseDataRef();               - check if data ref can be used
  37. **  DataHGetVolumeList();               - return list of volumes supported
  38. **  [DataHWrite();]                     - write data
  39. **  [DataHPreextend();]                 - extend file
  40. **  [DataHSetFileSize();]               - set file size
  41. **  DataHGetFreeSpace();                - get device free space
  42. **  [DataHCreateFile();]                - create file
  43. **  DataHGetPreferredBlockSize();       - get preferred block size
  44. **  DataHGetDeviceIndex();              - get unique device index
  45. **  DataHGetScheduleAheadTime();        - get preferred advance read time
  46. **  DataHPlaybackHints();               - provide data ref playback hints
  47. **  DataHSetOSFileReference();          - set mmioH as data reference
  48. **  DataHGetOSFileReference();          - get references from SetOSFile...
  49. **
  50. ********************************************************************************
  51. */
  52.  
  53. // Windows header files
  54. #include <windows.h>
  55. #include <windowsx.h>
  56. #include <mmsystem.h>
  57.  
  58. // dos headers
  59. #include <direct.h>
  60. #include <dos.h>
  61.  
  62. // Compiler header files
  63. #include <string.h>
  64. #include <ctype.h>
  65. #include <stdlib.h>
  66. #include <malloc.h>
  67. #include <io.h>
  68.  
  69. // Application header files
  70. #define INTERNAL_DHLR
  71. #include "datahp.h"
  72.  
  73. // four character type
  74.  
  75. #define ostypeOTHR QTFOURCC('o','t','h','r')
  76.  
  77. // macros
  78. #define DATAHPARM(x,y) GetPrivateProfileInt("Data Handler",x,y,QTW_PROFILE)
  79.  
  80. // prototypes for external functions
  81. DWORD _cdecl DataHEntry(void);
  82.  
  83. // Global data
  84. ComponentDescription cdTable =              // one component in this DLL
  85.   { ostypeDHLR                              // ostypeComponentType
  86.   , ostypeHNDL                              // ostypeComponentSubType
  87.   , ostypeOTHR                              // ostypeComponentManufacturer
  88.   , 0                                       // dwComponentFlags
  89.   , 0                                       // dwComponentFlagsMask
  90.   , ( ComponentRoutine) DataHEntry          // crEntryPoint
  91.   , 0                                       // hrsrcName
  92.   , 0                                       // hrsrcInfo
  93.   , 0                                       // hrsrcIcon
  94.   } ;
  95.  
  96. // EJECT PAGE 
  97. /*
  98. ********************************************************************************
  99. **
  100. ** Name: DataHOpen()
  101. **
  102. ** Description:
  103. **
  104. **  Opens an instance of the component.
  105. **
  106. **  The general data handler initialization is done here, so that any memory
  107. **  used will not be allocated until an instance of the data handler is actually
  108. **  opened.
  109. **
  110. ********************************************************************************
  111. */
  112. ComponentResult _cdecl DataHOpen( STKOFF_CMP so, ComponentInstance ci)
  113. {
  114.     void far *storageH, far *globalH;
  115.     DataHInstanceStoragePtr storage;
  116.     DataHGlobalStoragePtr globals;
  117.     
  118.     // allocate the cross-instance globals
  119.     globalH = (void far *)GetComponentRefcon(ci);
  120.     if(globalH == NULL)
  121.     {
  122.         // allocate global storage
  123.         globalH = (void far *)GlobalAlloc(GMEM_ZEROINIT, sizeof(DataHGlobalStorage));
  124.         if(globalH == NULL)
  125.             return(insufficientMemory);
  126.  
  127.         // set the refcon so that we know we have been initialized
  128.         SetComponentRefcon(ci, (long)globalH);
  129.     }
  130.         
  131.     globals = (DataHGlobalStoragePtr)GlobalLock((HGLOBAL)LOWORD(globalH));
  132.     if(globals == NULL)
  133.     {
  134.         GlobalFree((HGLOBAL)LOWORD(globalH));
  135.         return(insufficientMemory);
  136.     }
  137.  
  138.     // if first instance ever
  139.     if (!globals->mmioInitialized) {
  140.         globals->mmioInitialized = TRUE;    // mmio requires no initialization
  141.     }
  142.  
  143.     // allocate instance storage, all members zero init.
  144.     storageH = (void far *)GlobalAlloc(GMEM_ZEROINIT, sizeof(DataHInstanceStorage));
  145.     if(storageH == NULL)
  146.         return(insufficientMemory);
  147.     storage = (DataHInstanceStoragePtr)GlobalLock((HGLOBAL)LOWORD(storageH));
  148.     if(storage == NULL)
  149.     {
  150.         GlobalUnlock((HGLOBAL)LOWORD(globalH));
  151.         GlobalFree((HGLOBAL)LOWORD(storageH));
  152.         return(insufficientMemory);
  153.     }
  154.  
  155.     // init storage fields
  156.     storage->ci = ci;
  157.     storage->mmioH = mmioINVALID;       // invalid HMMIO handle indicates non-open session
  158.         
  159.     // set storage for this component
  160.     SetComponentInstanceStorage(ci, (LPVOID)storageH);
  161.     
  162.     // done
  163.     GlobalUnlock((HGLOBAL)LOWORD(storageH));
  164.     GlobalUnlock((HGLOBAL)LOWORD(globalH));
  165.     return(noErr);
  166. }
  167.  
  168. // EJECT PAGE 
  169. /*
  170. ********************************************************************************
  171. **
  172. ** Name: DataHClose()
  173. **
  174. ** Description:
  175. **
  176. **  Closes an instance of the component.
  177. **
  178. ********************************************************************************
  179. */
  180. ComponentResult _cdecl DataHClose( STKOFF_CMP so, ComponentInstance ci)  
  181. {
  182.     void far *storageH, far *globalH;
  183.     DataHInstanceStoragePtr storage;
  184.  
  185.     // locate instance storage
  186.     storageH = GetComponentInstanceStorage(ci);
  187.     if(storageH != NULL)
  188.     {
  189.         storage = (DataHInstanceStoragePtr)GlobalLock((HGLOBAL)LOWORD(storageH));
  190.         if(storage != NULL)
  191.         {
  192.             // close the mmio session if open
  193.             if (storage->mmioH != mmioINVALID) {
  194.                 mmioClose(storage->mmioH,0);
  195.             }
  196.             // release memory allocated for filename
  197.             if(storage->fileName)
  198.                 GlobalFree((HGLOBAL)storage->fileName);
  199.             
  200.             // release memory for instance storage
  201.             GlobalUnlock((HGLOBAL)LOWORD(storageH));
  202.             GlobalFree((HGLOBAL)LOWORD(storageH));
  203.         }
  204.     }
  205.     
  206.     // release global storage if this is the last instance of the component
  207.     if(CountComponentInstances(ci) == 1)
  208.     {
  209.         globalH = (void far *)GetComponentRefcon(ci);
  210.         if(globalH)
  211.         {
  212.             // do a global release of i/o subsystem here
  213.             
  214.             GlobalFree((HGLOBAL)LOWORD(globalH));
  215.             SetComponentRefcon(ci,NULL);
  216.         }
  217.     }   
  218.     return(noErr);
  219. }
  220.  
  221. // EJECT PAGE 
  222. /*
  223. ********************************************************************************
  224. **
  225. ** Name: DataHCanDo()
  226. **
  227. ** Description:
  228. **
  229. **  Returns TRUE if a call is supported.
  230. **
  231. ********************************************************************************
  232. */
  233. ComponentResult _cdecl DataHCanDo( STKOFF_CMP so, long lFunctionSelector)
  234. {
  235.     switch (lFunctionSelector)
  236.     {
  237.         /* standard component manager calls */
  238.         case kDataVersionSelector:
  239.         case kDataCanDoSelector:
  240.         case kDataCloseSelector:
  241.         case kDataOpenSelector:
  242.         
  243.         /* data handler calls */
  244.         case kDataGetDataSelector:
  245.         case kDataOpenForReadSelector:
  246.         case kDataCloseForReadSelector:
  247.         case kDataSetDatRefSelector:
  248.         case kDataGetDataRefSelector:
  249.         case kDataCompareDataRefSelector:
  250.         case kDataTaskSelector:
  251.         case kDataScheduleDataSelector:
  252.         case kDataFinishDataSelector:
  253.         case kDataFlushCacheSelector:
  254.         case kDataResolveDataRefSelector:
  255.         case kDataGetFileSizeSelector:
  256.         case kDataCanUseDataRefSelector:
  257.         case kDataGetVolumeListSelector:
  258.         case kDataPlaybackHintsSelector:
  259.         case kDataSetOSFileReferenceSelector:
  260.         case kDataGetOSFileReferenceSelector:
  261.             return(TRUE);
  262.             break;
  263.         default:
  264.             return(FALSE);
  265.             break;
  266.     }
  267.     
  268.     return(FALSE);
  269. }
  270.  
  271. // EJECT PAGE 
  272. /*
  273. ********************************************************************************
  274. **
  275. ** Name: DataHVersion()
  276. **
  277. ** Description:
  278. **
  279. **  Returns version number of the component.
  280. **
  281. ********************************************************************************
  282. */
  283. ComponentResult _cdecl DataHVersion( STKOFF_CMP so, ComponentInstance ci)
  284. {
  285.     return(kDataHVersion);
  286. }
  287.  
  288. // EJECT PAGE 
  289. /*
  290. ********************************************************************************
  291. **
  292. ** Name: DataHGetData()
  293. **
  294. ** Description:
  295. **
  296. **  Synchronous data read.
  297. **
  298. ********************************************************************************
  299. */
  300. ComponentResult _cdecl DataHGetData (DHLR_FPARM1
  301.     Handle h,       // handle to destination of data
  302.     long hOffset,   // offset into handle to place data
  303.     long offset,    // offset within file of data to read
  304.     long size)      // amount of data to read
  305. {
  306.     void FAR *storageH = instanceStorage;
  307.     DataHInstanceStoragePtr storage;
  308.     Ptr dataPtr;
  309.     OSErr oserr = noErr;
  310.  
  311.     // lock the storage
  312.     storage = (DataHInstanceStoragePtr)GlobalLock((HGLOBAL)LOWORD(storageH));
  313.     if(storage == NULL)
  314.         return(insufficientMemory);
  315.  
  316.     // verify that we have an open file
  317.     if(storage->mmioH  == mmioINVALID)
  318.     {
  319.         GlobalUnlock((HGLOBAL)LOWORD(storageH));
  320.         return(dataNotOpenForRead);
  321.     }
  322.  
  323.     // check dest
  324.     if (hOffset + size > GetHandleSize(h)) {
  325.         GlobalUnlock((HGLOBAL)LOWORD(storageH));
  326.         return(insufficientMemory);
  327.     }
  328.  
  329.     // lock and deref the user handle
  330.     HLock(h);
  331.     dataPtr = (Ptr)DereferenceHandle(h);
  332.     if(dataPtr == NULL)
  333.     {
  334.         HUnlock(h);
  335.         GlobalUnlock((HGLOBAL)LOWORD(storageH));
  336.         return(insufficientMemory);
  337.     }
  338.  
  339.     // build the pointer to the destination area
  340.     dataPtr += hOffset;
  341.  
  342.     if (storage->mmioH != mmioINVALID) {
  343.         if (offset != mmioSeek(storage->mmioH,offset,SEEK_SET)) {
  344.             oserr = readErr;
  345.         } else {
  346.             if (size != mmioRead(storage->mmioH,(LPSTR)dataPtr,size)) {               
  347.                 oserr = readErr;
  348.             }
  349.         }
  350.     }
  351.     
  352.     // done
  353.     HUnlock(h);
  354.  
  355.     GlobalUnlock((HGLOBAL)LOWORD(storageH));
  356.     return(oserr);
  357. }
  358.  
  359. // EJECT PAGE 
  360. /*
  361. ********************************************************************************
  362. **
  363. ** Name: DataHPutData()
  364. **
  365. ** Description:
  366. **
  367. **  Synchronous write.  Not supported.
  368. **
  369. ********************************************************************************
  370. */
  371. ComponentResult _cdecl DataHPutData (DHLR_FPARM1
  372.     Handle h,
  373.     long hOffset,
  374.     long *offset,
  375.     long size)
  376. {
  377.     return(badComponentSelector);
  378. }
  379.  
  380. // EJECT PAGE 
  381. /*
  382. ********************************************************************************
  383. **
  384. ** Name: DataHFlushData()
  385. **
  386. ** Description:
  387. **
  388. **  Flush unwritten data.  Not supported.
  389. **
  390. ********************************************************************************
  391. */
  392. ComponentResult _cdecl DataHFlushData (DHLR_FPARM2)
  393. {
  394.     return(badComponentSelector);
  395. }
  396.  
  397. // EJECT PAGE 
  398. /*
  399. ********************************************************************************
  400. **
  401. ** Name: DataHOpenForWrite()
  402. **
  403. ** Description:
  404. **
  405. **  Open data reference for write access.  Not supported.
  406. **
  407. ********************************************************************************
  408. */
  409. ComponentResult _cdecl DataHOpenForWrite (DHLR_FPARM2)
  410. {
  411.     return(badComponentSelector);
  412. }
  413.  
  414. // EJECT PAGE 
  415. /*
  416. ********************************************************************************
  417. **
  418. ** Name: DataHCloseForWrite()
  419. **
  420. ** Description:
  421. **
  422. **  Close data reference that has been opened for write access.  Not supported.
  423. **
  424. ********************************************************************************
  425. */
  426. ComponentResult _cdecl DataHCloseForWrite (DHLR_FPARM2)
  427. {
  428.     return(badComponentSelector);
  429. }
  430.  
  431. // EJECT PAGE 
  432. /*
  433. ********************************************************************************
  434. **
  435. ** Name: DataHOpenForRead()
  436. **
  437. ** Description:
  438. **
  439. **  Open data reference for read access.
  440. **
  441. ********************************************************************************
  442. */
  443. ComponentResult _cdecl DataHOpenForRead (DHLR_FPARM2)
  444. {
  445.     void far *storageH = instanceStorage;
  446.     DataHInstanceStoragePtr storage;
  447.     char FAR *fileName;
  448.     OSErr oserr = noErr;
  449.     
  450.     storage = (DataHInstanceStoragePtr)GlobalLock((HGLOBAL)LOWORD(storageH));
  451.     if(storage == NULL)
  452.         return(insufficientMemory);
  453.  
  454.     // must have a data reference
  455.     if(storage->fileName == NULL)
  456.     {
  457.         GlobalUnlock((HGLOBAL)LOWORD(storageH));
  458.         return(dataNoDataRef);
  459.     }
  460.     
  461.     // dereference the handle to the file name
  462.     fileName = (char FAR *)GlobalLock(storage->fileName);
  463.     if(fileName == NULL)
  464.     {
  465.         GlobalUnlock((HGLOBAL)LOWORD(storageH));
  466.         return(invalidDataRef);     
  467.     }
  468.     
  469.     // open the movie file
  470.     storage->mmioH = mmioOpen(fileName, NULL, MMIO_READ | MMIO_DENYWRITE);
  471.     if (storage->mmioH == mmioINVALID)
  472.     {
  473.         oserr = invalidDataRef;
  474.     }
  475.     
  476.     // unlock handles
  477.     GlobalUnlock(storage->fileName);
  478.     GlobalUnlock((HGLOBAL)LOWORD(storageH));
  479.     
  480.     return(oserr);
  481. }
  482.  
  483. // EJECT PAGE 
  484. /*
  485. ********************************************************************************
  486. **
  487. ** Name: DataHCloseForRead()
  488. **
  489. ** Description:
  490. **
  491. **  Close data reference that has been opened for read access.
  492. **
  493. ********************************************************************************
  494. */
  495. ComponentResult _cdecl DataHCloseForRead (DHLR_FPARM2)
  496. {
  497.     void far *storageH = instanceStorage;
  498.     DataHInstanceStoragePtr storage;
  499.     OSErr oserr = noErr;
  500.     
  501.     // locate instance storage
  502.     storage = (DataHInstanceStoragePtr)GlobalLock((HGLOBAL)LOWORD(storageH));
  503.     if(storage == NULL)
  504.         return(insufficientMemory);
  505.  
  506.     // close the file
  507.     if (storage->mmioH != mmioINVALID) {
  508.         mmioClose(storage->mmioH,0);
  509.         storage->mmioH = mmioINVALID;
  510.         if (storage->fileName) {
  511.             GlobalFree(storage->fileName);
  512.             storage->fileName = NULL;
  513.         }
  514.     } else {
  515.        oserr = dataNotOpenForRead;
  516.     }
  517.         
  518.     GlobalUnlock((HGLOBAL)LOWORD(storageH));
  519.     return(oserr);
  520. }
  521.  
  522. // EJECT PAGE 
  523. /*
  524. ********************************************************************************
  525. **
  526. ** Name: DataHSetDataRef()
  527. **
  528. ** Description:
  529. **
  530. **  Set data reference for this component instance.  In this mmio sample for QTW
  531. **  the data reference is the file path.  The input data reference is assumed to
  532. **  be a locked Handle.
  533. **
  534. **  this sample implementation assumes 0x00 terminated strings
  535. **
  536. ********************************************************************************
  537. */
  538. ComponentResult _cdecl DataHSetDataRef (DHLR_FPARM1
  539.     Handle dataRef)
  540. {
  541.     char far *strIn;
  542.     char far *myStr;    
  543.     int len;
  544.     HLOCAL mem;
  545.     void far *storageH = instanceStorage;
  546.     DataHInstanceStoragePtr storage;
  547.  
  548.     // locate instance storage
  549.     storage = (DataHInstanceStoragePtr)GlobalLock((HGLOBAL)LOWORD(storageH));
  550.     if(storage == NULL)
  551.         return(insufficientMemory);
  552.         
  553.     // release any existing allocated memory
  554.     // some data handler implementations may want to close the i/o system
  555.     // when the data ref changes, then prep for the new dataref
  556.     if(storage->fileName)
  557.     {
  558.         GlobalFree(storage->fileName);
  559.         storage->fileName = NULL;
  560.     }
  561.     
  562.     // deref the path
  563.     strIn = (char far *)DereferenceHandle(dataRef);
  564.     if(strIn == NULL)
  565.     {
  566.         GlobalUnlock((HGLOBAL)LOWORD(storageH));
  567.         return(invalidUserDataHandle);
  568.     }
  569.     len = _fstrlen(strIn);
  570.     
  571.     // allocate the memory, allow extra for ASCIIZ
  572.     mem = GlobalAlloc(GMEM_ZEROINIT, len+1);
  573.     if(mem == NULL)
  574.     {
  575.         GlobalUnlock((HGLOBAL)LOWORD(storageH));
  576.         return(insufficientMemory);
  577.     }
  578.         
  579.     // copy data
  580.     myStr = (char FAR *)GlobalLock(mem);
  581.     if (myStr == NULL) {
  582.         GlobalUnlock((HGLOBAL)LOWORD(storageH));
  583.         return(insufficientMemory);
  584.     }
  585.     
  586.     while (*myStr++ = *strIn++) /* empty body */;
  587.     GlobalUnlock(mem);
  588.         
  589.     // store handle
  590.     storage->fileName = mem;
  591.     
  592.     // done
  593.     GlobalUnlock((HGLOBAL)LOWORD(storageH));
  594.     return(noErr);
  595. }
  596.  
  597. // EJECT PAGE 
  598. /*
  599. ********************************************************************************
  600. **
  601. ** Name: DataHGetDataRef()
  602. **
  603. ** Description:
  604. **
  605. **  Return data reference for this component instance.
  606. **
  607. ** this sample implementation assumes 0x00 terminated strings
  608. **
  609. ********************************************************************************
  610. */
  611. ComponentResult _cdecl DataHGetDataRef (DHLR_FPARM1
  612.     Handle *dataRef)
  613. {
  614.     char far *strOut;
  615.     char far *myStr;    
  616.     int len;
  617.     Handle memH;
  618.     void far *storageH = instanceStorage;
  619.     DataHInstanceStoragePtr storage;
  620.     
  621.     if (dataRef == NULL) {
  622.         return(paramErr);
  623.     }
  624.  
  625.     // locate instance storage
  626.     storage = (DataHInstanceStoragePtr)GlobalLock((HGLOBAL)LOWORD(storageH));
  627.     if(storage == NULL)
  628.         return(insufficientMemory);
  629.     
  630.     // deref the path
  631.     myStr = (char far *)GlobalLock(storage->fileName);
  632.     if (myStr == NULL) {
  633.         GlobalUnlock((HGLOBAL)LOWORD(storageH));
  634.         return(insufficientMemory);
  635.     }
  636.     
  637.     len = _fstrlen(myStr);
  638.     
  639.     // allocate the memory, allow for asciiz
  640.     memH = NewHandle(len+1);
  641.     if(memH == NULL)
  642.     {
  643.         GlobalUnlock(storage->fileName);
  644.         GlobalUnlock((HGLOBAL)LOWORD(storageH));
  645.         return(insufficientMemory);
  646.     }
  647.         
  648.     // copy data
  649.     HLock(memH);
  650.     strOut = (char far *)DereferenceHandle(memH);
  651.     if(strOut == NULL)
  652.     {
  653.         GlobalUnlock(storage->fileName);
  654.         GlobalUnlock((HGLOBAL)LOWORD(storageH));
  655.         return(insufficientMemory);
  656.     }
  657.     while (*strOut++ = *myStr++) /* empty body */;
  658.     HUnlock(memH);
  659.         
  660.     // store handle
  661.     *dataRef = memH;
  662.     
  663.     // done
  664.     GlobalUnlock((HGLOBAL)LOWORD(storageH));
  665.     return(noErr);
  666. }
  667.  
  668. // EJECT PAGE 
  669. /*
  670. ********************************************************************************
  671. **
  672. ** Name: DataHCompareDataRef()
  673. **
  674. ** Description:
  675. **
  676. **  Compare provided data reference with the one established for this
  677. **  component instance.
  678. **
  679. ** this sample implementation tests for bitwise equality of 0x00 terminated strings
  680. **
  681. ********************************************************************************
  682. */
  683. ComponentResult _cdecl DataHCompareDataRef (DHLR_FPARM1
  684.     Handle dataRef,
  685.     Boolean *equal)
  686. {
  687.     char far *inStr;
  688.     char far *myStr;    
  689.     int myLen, inLen;
  690.     void far *storageH = instanceStorage;
  691.     DataHInstanceStoragePtr storage;
  692.     
  693.     if (equal == NULL) {
  694.         return(paramErr);
  695.     }
  696.  
  697.     // locate instance storage
  698.     storage = (DataHInstanceStoragePtr)GlobalLock((HGLOBAL)LOWORD(storageH));
  699.     if(storage == NULL)
  700.         return(insufficientMemory);
  701.     
  702.     // deref the paths
  703.     myStr = (char FAR *)GlobalLock(storage->fileName);
  704.     if(myStr == NULL)
  705.     {
  706.         GlobalUnlock((HGLOBAL)LOWORD(storageH));
  707.         return(insufficientMemory);
  708.     }
  709.     myLen = _fstrlen(myStr);
  710.     
  711.     HLock(dataRef);
  712.     inStr = (char far *)DereferenceHandle(dataRef);
  713.     if(inStr == NULL)
  714.     {
  715.         HUnlock(dataRef);
  716.         GlobalUnlock(storage->fileName);
  717.         GlobalUnlock((HGLOBAL)LOWORD(storageH));
  718.         return(invalidUserDataHandle);
  719.     }
  720.     inLen = _fstrlen(inStr);
  721.     
  722.     // assume equal
  723.     *equal = TRUE;
  724.     
  725.     // check lengths
  726.     if(myLen != inLen)
  727.     {
  728.         *equal = FALSE;
  729.     }
  730.     else
  731.     {
  732.         // lengths are same, so check contents
  733.         for(int i = 0; i < myLen; i++)
  734.         {
  735.             if(toupper(*myStr) != toupper(*inStr))
  736.             {
  737.                 *equal = FALSE;
  738.                 break;
  739.             }
  740.             myStr++;
  741.             inStr++;
  742.         }
  743.     }
  744.             
  745.     // done
  746.     HUnlock(dataRef);
  747.     GlobalUnlock(storage->fileName);
  748.     GlobalUnlock((HGLOBAL)LOWORD(storageH));
  749.     return(noErr);
  750. }
  751.  
  752. // EJECT PAGE 
  753. /*
  754. ********************************************************************************
  755. **
  756. ** Name: DataHTask()
  757. **
  758. ** Description:
  759. **
  760. **  Provides time slices for the data handler to perform background operations.
  761. **
  762. ********************************************************************************
  763. */
  764. ComponentResult _cdecl DataHTask (DHLR_FPARM2)
  765. {
  766.     void far *storageH = instanceStorage;
  767.     DataHInstanceStoragePtr storage;
  768.     OSErr err = noErr;
  769.     
  770.     // locate instance storage
  771.     storage = (DataHInstanceStoragePtr)GlobalLock((HGLOBAL)LOWORD(storageH));
  772.     if(storage == NULL)
  773.         return(insufficientMemory);
  774.         
  775.     // do appropriate background processing here.
  776.     // do not use synchronous (blocking) i/o calls if at all avoidable
  777.  
  778.     // done
  779.     GlobalUnlock((HGLOBAL)LOWORD(storageH));
  780.     return(err);
  781. }
  782.  
  783. // EJECT PAGE 
  784. /*
  785. ********************************************************************************
  786. **
  787. ** Name: DataHScheduleData()
  788. **
  789. ** Description:
  790. **
  791. **  Async or synchronous read operation.
  792. **  completion routine not call under all error conditions in this implementation
  793. **
  794. ********************************************************************************
  795. */
  796. ComponentResult _cdecl DataHScheduleData (DHLR_FPARM1
  797.     Ptr placeToPutDataPtr,
  798.     long fileOffset,
  799.     long dataSize,
  800.     long refCon,
  801.     DataHSchedulePtr scheduleRec,
  802.     DHCompleteProc completionRtn)
  803. {
  804.     void far *storageH = instanceStorage;
  805.     DataHInstanceStoragePtr storage;
  806.     OSErr oserr = noErr;
  807.     
  808.     // lock instance storage
  809.     storage = (DataHInstanceStoragePtr)GlobalLock((HGLOBAL)LOWORD(storageH));
  810.     if(storage == NULL)
  811.         return(insufficientMemory);
  812.  
  813.     // verify that we have an open file
  814.     if(storage->mmioH  == mmioINVALID)
  815.     {
  816.         GlobalUnlock((HGLOBAL)LOWORD(storageH));
  817.         return(dataNotOpenForRead);
  818.     }
  819.  
  820.     // read the data right now...synchronous read
  821.     if(scheduleRec == NULL)
  822.     {
  823.         if (storage->mmioH != mmioINVALID) {
  824.             if (fileOffset == mmioSeek(storage->mmioH,fileOffset,SEEK_SET)) {
  825.                 if (dataSize != mmioRead(storage->mmioH, (char far *)placeToPutDataPtr, dataSize)) {
  826.                     oserr = readErr;
  827.                 }
  828.             } else {
  829.                 oserr = readErr;
  830.             }
  831.         }
  832.         
  833.         // do the callback
  834.         if(completionRtn)
  835.             (*completionRtn)(placeToPutDataPtr, refCon, oserr);
  836.     }
  837.     else // the request is asynchronous
  838.     {
  839.         // add to queue and initiate at appropriate time
  840.         /* null body */;
  841.     }
  842.  
  843.     // done
  844.     GlobalUnlock((HGLOBAL)LOWORD(storageH));
  845.     return(oserr);
  846. }
  847.  
  848. // EJECT PAGE 
  849. /*
  850. ********************************************************************************
  851. **
  852. ** Name: DataHFinishData()
  853. **
  854. ** Description:
  855. **
  856. **  Complete specified async read requests.
  857. **
  858. ********************************************************************************
  859. */
  860. ComponentResult _cdecl DataHFinishData (DHLR_FPARM1
  861.     Ptr placeToPutDataPtr,
  862.     Boolean cancel )
  863. {
  864.     return(badComponentSelector);
  865. }
  866.  
  867. // EJECT PAGE 
  868. /*
  869. ********************************************************************************
  870. **
  871. ** Name: DataHFlushCache()
  872. **
  873. ** Description:
  874. **
  875. **  Flush read caches.
  876. **
  877. ********************************************************************************
  878. */
  879. ComponentResult _cdecl DataHFlushCache (DHLR_FPARM2)
  880. {
  881.     return(noErr);
  882. }
  883.  
  884. // EJECT PAGE 
  885. /*
  886. ********************************************************************************
  887. **
  888. ** Name: DataHResolveDataRef()
  889. **
  890. ** Description:
  891. **
  892. **  Resolves a data reference.  No operation is performed, as a data reference
  893. **  under this sample datahandler for QTW is a path name.
  894. **
  895. ********************************************************************************
  896. */
  897. ComponentResult _cdecl DataHResolveDataRef (DHLR_FPARM1
  898.     Handle dataRef,
  899.     Boolean *wasChanged,
  900.     Boolean userInterfaceAllowed)
  901. {
  902.     if (wasChanged != NULL) {
  903.         *wasChanged = FALSE;
  904.     }
  905.     return(noErr);
  906. }
  907.  
  908. // EJECT PAGE 
  909. /*
  910. ********************************************************************************
  911. **
  912. ** Name: DataHGetFileSize()
  913. **
  914. ** Description:
  915. **
  916. **  Return size of data reference.  The data reference must already be open
  917. **  for this call to work.
  918. **
  919. ********************************************************************************
  920. */
  921. ComponentResult _cdecl DataHGetFileSize (DHLR_FPARM1
  922.     long *fileSize)
  923. {
  924.     void far *storageH = instanceStorage;
  925.     DataHInstanceStoragePtr storage;
  926.     LONG lCurrentPos;
  927.     OSErr oserr = noErr;
  928.     
  929.     if (fileSize == NULL) {
  930.         return paramErr;
  931.     }
  932.     
  933.     // locate instance storage
  934.     storage = (DataHInstanceStoragePtr)GlobalLock((HGLOBAL)LOWORD(storageH));
  935.     if(storage == NULL)
  936.         return(insufficientMemory);
  937.  
  938.     // file must be open
  939.     // verify that we have an open file
  940.     if(storage->mmioH  != mmioINVALID) {
  941.         // save current pos
  942.         lCurrentPos = mmioSeek(storage->mmioH,0,SEEK_CUR);
  943.         if (lCurrentPos >= 0) {
  944.             // get ending pos
  945.             *fileSize = mmioSeek(storage->mmioH,0,SEEK_END);
  946.             if (*fileSize >= 0) {
  947.                 // reset to prior position
  948.                 if (mmioSeek(storage->mmioH,lCurrentPos,SEEK_SET) < 0) {
  949.                     oserr = readErr;
  950.                 }
  951.             } else {
  952.                 oserr = readErr;
  953.             }
  954.         } else {
  955.             oserr = readErr;
  956.         }
  957.     } else {
  958.         oserr = dataNotOpenForRead;
  959.     }
  960.     
  961.     // done
  962.     GlobalUnlock((HGLOBAL)LOWORD(storageH));
  963.     return(oserr);
  964. }
  965.  
  966. // EJECT PAGE 
  967. /*
  968. ********************************************************************************
  969. **
  970. ** Name: DataHCanUseDataRef()
  971. **
  972. ** Description:
  973. **
  974. **  Return flags indicating the ability for the data handler to access the
  975. **  data reference.
  976. **
  977. **  Currently only reading of files is supported.
  978. **
  979. ********************************************************************************
  980. */
  981. ComponentResult _cdecl DataHCanUseDataRef (DHLR_FPARM1
  982.     Handle dataRef,
  983.     DataHUseFlags *useFlags)
  984. {
  985.     if (useFlags != NULL) {
  986.         *useFlags = kDataHCanRead;
  987.     }
  988.     return(noErr);
  989. }
  990.  
  991. // EJECT PAGE 
  992. /*
  993. ********************************************************************************
  994. **
  995. ** Name: DataHGetVolumeList()
  996. **
  997. ** Description:
  998. **
  999. **  Return a list of volumes supported by this data handler.
  1000. **
  1001. ********************************************************************************
  1002. */
  1003. ComponentResult _cdecl DataHGetVolumeList (DHLR_FPARM1
  1004.     DataHVolumeList *volumeList)
  1005. {
  1006.     return(badComponentSelector);
  1007. }
  1008.  
  1009. // EJECT PAGE 
  1010. /*
  1011. ********************************************************************************
  1012. **
  1013. ** Name: DataHWrite()
  1014. **
  1015. ** Description:
  1016. **
  1017. **  Write data to data reference.  Not supported.
  1018. **
  1019. ********************************************************************************
  1020. */
  1021. ComponentResult _cdecl DataHWrite (DHLR_FPARM1
  1022.     Ptr data,
  1023.     long offset,
  1024.     long size,
  1025.     DHCompleteProc completion,
  1026.     long refcon)
  1027. {
  1028.     return(badComponentSelector);
  1029. }
  1030.  
  1031. // EJECT PAGE 
  1032. /*
  1033. ********************************************************************************
  1034. **
  1035. ** Name: DataHPreextend()
  1036. **
  1037. ** Description:
  1038. **
  1039. **  Preextend the data reference.  Not supported.
  1040. **
  1041. ********************************************************************************
  1042. */
  1043. ComponentResult _cdecl DataHPreextend (DHLR_FPARM1
  1044.     long maxToAdd,
  1045.     long *spaceAdded)
  1046. {
  1047.     return(badComponentSelector);
  1048. }
  1049.  
  1050. // EJECT PAGE 
  1051. /*
  1052. ********************************************************************************
  1053. **
  1054. ** Name: DataHSetFileSize()
  1055. **
  1056. ** Description:
  1057. **
  1058. **  Change file size of data reference.  Not supported.
  1059. **
  1060. ********************************************************************************
  1061. */
  1062. ComponentResult _cdecl DataHSetFileSize (DHLR_FPARM1
  1063.     long fileSize)
  1064. {
  1065.     return(badComponentSelector);
  1066. }
  1067.  
  1068. // EJECT PAGE 
  1069. /*
  1070. ********************************************************************************
  1071. **
  1072. ** Name: DataHGetFreeSpace()
  1073. **
  1074. ** Description:
  1075. **
  1076. **  Return amount of free space on the device holding the data reference.
  1077. **  Not supported.
  1078. **
  1079. ********************************************************************************
  1080. */
  1081. ComponentResult _cdecl DataHGetFreeSpace (DHLR_FPARM1
  1082.     unsigned long *freeSize)
  1083. {
  1084.     void far *storageH = instanceStorage;
  1085.     DataHInstanceStoragePtr storage;
  1086.     char FAR *fileName;
  1087.     int deviceIndex;
  1088.     OSErr err;
  1089.     
  1090.     // locate instance storage
  1091.     storage = (DataHInstanceStoragePtr)GlobalLock((HGLOBAL)LOWORD(storageH));
  1092.     if(storage == NULL)
  1093.         return(insufficientMemory);
  1094.  
  1095.     // must have a data reference
  1096.     if(storage->fileName == NULL)
  1097.     {
  1098.         GlobalUnlock((HGLOBAL)LOWORD(storageH));
  1099.         return(dataNoDataRef);
  1100.     }
  1101.     
  1102.     // dereference the handle to the file name
  1103.     fileName = (char FAR *)GlobalLock(storage->fileName);
  1104.     if(fileName == NULL)
  1105.     {
  1106.         GlobalUnlock((HGLOBAL)LOWORD(storageH));
  1107.         return(invalidDataRef);     
  1108.     }
  1109.     
  1110.     // get the index, use the drive letter.  If the caller didn't
  1111.     // specify a drive letter, then get the current drive.  The
  1112.     // index is 0 for A:, 1 for B:, ...
  1113.     if(fileName[1] != ':')
  1114.         deviceIndex = _getdrive();
  1115.     else
  1116.         deviceIndex = tolower(fileName[0])-'a' +1;
  1117.     
  1118.     // get the free space on the device
  1119.     _diskfree_t *pfreeSpace = (_diskfree_t *)malloc(sizeof _diskfree_t);
  1120.     if (pfreeSpace != NULL) {
  1121.         if(_dos_getdiskfree(deviceIndex, pfreeSpace))
  1122.         {
  1123.             err = couldNotResolveDataRef;
  1124.         }
  1125.         else
  1126.         {
  1127.             // calculate the free space from the dos info returned
  1128.             if (freeSize != NULL) {
  1129.                 *freeSize = pfreeSpace->avail_clusters * pfreeSpace->sectors_per_cluster * pfreeSpace->bytes_per_sector;
  1130.             }
  1131.             err = noErr;    
  1132.         }
  1133.         free(pfreeSpace);
  1134.     } else {
  1135.         err = insufficientMemory;
  1136.     }
  1137.                 
  1138.     // unlock handles
  1139.     GlobalUnlock(storage->fileName);
  1140.     GlobalUnlock((HGLOBAL)LOWORD(storageH));
  1141.     
  1142.     // done
  1143.     return(err);
  1144. }
  1145.  
  1146. // EJECT PAGE 
  1147. /*
  1148. ********************************************************************************
  1149. **
  1150. ** Name: DataHCreateFile()
  1151. **
  1152. ** Description:
  1153. **
  1154. **  Create a file corresponding to the data reference.  Not supported.
  1155. **
  1156. ********************************************************************************
  1157. */
  1158. ComponentResult _cdecl DataHCreateFile (DHLR_FPARM1
  1159.     OSType creator,
  1160.     Boolean deleteExisting)
  1161. {
  1162.     return(badComponentSelector);
  1163. }
  1164.  
  1165. // EJECT PAGE 
  1166. /*
  1167. ********************************************************************************
  1168. **
  1169. ** Name: DataHGetPreferredBlockSize()
  1170. **
  1171. ** Description:
  1172. **
  1173. **  Return the block size, in bytes, the data handler prefers to work with.
  1174. **
  1175. ********************************************************************************
  1176. */
  1177. ComponentResult _cdecl DataHGetPreferredBlockSize (DHLR_FPARM1
  1178.     long *blockSize)
  1179. {
  1180.     // we are happiest with blocks of this size
  1181.     if (blockSize != NULL) {
  1182.         *blockSize = MMIO_DEFAULTBUFFER;
  1183.     }
  1184.     return(noErr);
  1185. }
  1186.  
  1187. // EJECT PAGE 
  1188. /*
  1189. ********************************************************************************
  1190. **
  1191. ** Name: DataHGetDeviceIndex()
  1192. **
  1193. ** Description:
  1194. **
  1195. **  Return a unique identifier for the device the data reference resides on.
  1196. **
  1197. ********************************************************************************
  1198. */
  1199. ComponentResult _cdecl DataHGetDeviceIndex (DHLR_FPARM1
  1200.     long *deviceIndex)
  1201. {
  1202.     void far *storageH = instanceStorage;
  1203.     DataHInstanceStoragePtr storage;
  1204.     char far *fileName;
  1205.     
  1206.     storage = (DataHInstanceStoragePtr)GlobalLock((HGLOBAL)LOWORD(storageH));
  1207.     if(storage == NULL)
  1208.         return(insufficientMemory);
  1209.  
  1210.     // must have a data reference
  1211.     if(storage->fileName == NULL)
  1212.     {
  1213.         GlobalUnlock((HGLOBAL)LOWORD(storageH));
  1214.         return(dataNoDataRef);
  1215.     }
  1216.     
  1217.     // dereference the handle to the file name
  1218.     fileName = (char far *)GlobalLock(storage->fileName);
  1219.     if(fileName == NULL)
  1220.     {
  1221.         GlobalUnlock((HGLOBAL)LOWORD(storageH));
  1222.         return(invalidDataRef);     
  1223.     }
  1224.     
  1225.     // get the index, use the drive letter.  If the caller didn't
  1226.     // specify a drive letter, then get the current drive.  The
  1227.     // index is 1 for A:, 2 for B:, ...
  1228.     if (deviceIndex != NULL) {
  1229.         if(fileName[1] != ':')
  1230.             *deviceIndex = _getdrive();
  1231.         else
  1232.             *deviceIndex = (long)(tolower(fileName[0])-'a'+1);
  1233.     }            
  1234.     // unlock handles
  1235.     GlobalUnlock(storage->fileName);
  1236.     GlobalUnlock((HGLOBAL)LOWORD(storageH));
  1237.     
  1238.     // done
  1239.     return(noErr);
  1240. }
  1241.  
  1242. // EJECT PAGE 
  1243. /*
  1244. ********************************************************************************
  1245. **
  1246. ** Name: DataHGetScheduleAheadTime()
  1247. **
  1248. ** Description:
  1249. **
  1250. **  Return schedule ahead time that the data handler prefers.  Currently
  1251. **  an arbitrary value is returned.
  1252. **
  1253. ********************************************************************************
  1254. */
  1255. ComponentResult _cdecl DataHGetScheduleAheadTime (DHLR_FPARM1
  1256.     long *millisecs)
  1257. {
  1258.     // 1/2 second, close approximation to old sound media read ahead
  1259.     if (millisecs != NULL) {
  1260.         *millisecs = 500;
  1261.     }
  1262.     return(noErr);
  1263. }
  1264.  
  1265. // EJECT PAGE 
  1266. /*
  1267. ********************************************************************************
  1268. **
  1269. ** Name: DataHPlaybackHints()
  1270. **
  1271. ** Description:
  1272. **
  1273. **  Provides hints about the data reference being accessed.  This function
  1274. **  may be called at any time, even during movie playback if the user has
  1275. **  made edits to the movie.
  1276. **
  1277. ********************************************************************************
  1278. */
  1279. ComponentResult _cdecl DataHPlaybackHints (DHLR_FPARM1
  1280.     long flags,
  1281.     unsigned long minFileOffset,
  1282.     unsigned long maxFileOffset,
  1283.     long bytesPerSecond)
  1284. {
  1285.     void far *storageH = instanceStorage;
  1286.     DataHInstanceStoragePtr storage;
  1287.  
  1288.     // locate instance storage
  1289.     storage = (DataHInstanceStoragePtr)GlobalLock((HGLOBAL)LOWORD(storageH));
  1290.     if(storage == NULL)
  1291.         return(insufficientMemory);
  1292.  
  1293.     // store playback hints
  1294.     storage->minFileOffset = minFileOffset;
  1295.     storage->maxFileOffset = maxFileOffset;
  1296.     storage->bytesPerSecond = bytesPerSecond;
  1297.     
  1298.     // done 
  1299.     GlobalUnlock((HGLOBAL)LOWORD(storageH));
  1300.     return(noErr);
  1301. }
  1302.  
  1303. // EJECT PAGE 
  1304. /*
  1305. ********************************************************************************
  1306. **
  1307. ** Name: DataHSetOSFileReference()
  1308. **
  1309. ** Description:
  1310. **
  1311. **  Set the file reference directly to an already open file.  This call
  1312. **  exists because NewMovieFromDataFork() is only given an HFILE to work with,
  1313. **  and MS-Windows can't backup to the filename from just the HFILE
  1314. **  without using lots of undocumented stuff.
  1315. **
  1316. ********************************************************************************
  1317. */
  1318. ComponentResult _cdecl DataHSetOSFileReference (DHLR_FPARM1
  1319.     long fileRef,
  1320.     long flags)
  1321. {
  1322.     void far *storageH = instanceStorage;
  1323.     DataHInstanceStoragePtr storage;
  1324.     OSErr oserr = noErr;
  1325.     MMIOINFO info;
  1326.     int newFile;
  1327.  
  1328.     // locate instance storage
  1329.     storage = (DataHInstanceStoragePtr)GlobalLock((HGLOBAL)LOWORD(storageH));
  1330.     if(storage == NULL)
  1331.         return(insufficientMemory);
  1332.  
  1333.     // make sure we are not already open via the regular data reference
  1334.     if(storage->mmioH != mmioINVALID) {
  1335.         GlobalUnlock((HGLOBAL)LOWORD(storageH));
  1336.         return(invalidDataRef);
  1337.     }
  1338.     
  1339.     newFile = _dup((int)fileRef);   // note that HFILE and C runtime file handle are polymorphic
  1340.     
  1341.     // assign the file reference
  1342.     // cast from an HFILE to an HMMIO
  1343.     storage->lFlags = flags;
  1344.     _fmemset (&info, 0, sizeof info);
  1345.     info.adwInfo[0] = (DWORD)newFile;
  1346.     storage->mmioH = mmioOpen (NULL, &info, MMIO_READ | MMIO_DENYWRITE);
  1347.  
  1348.     if(storage->mmioH == mmioINVALID) {
  1349.         oserr = invalidDataRef;
  1350.     }
  1351.     
  1352.     // done 
  1353.     GlobalUnlock((HGLOBAL)LOWORD(storageH));
  1354.     return(oserr);
  1355. }
  1356.  
  1357. // EJECT PAGE 
  1358. /*
  1359. ********************************************************************************
  1360. **
  1361. ** Name: DataHGetOSFileReference()
  1362. **
  1363. ** Description:
  1364. **
  1365. **  Returns the file reference set by SetOSFileReference();
  1366. **
  1367. ********************************************************************************
  1368. */
  1369. ComponentResult _cdecl DataHGetOSFileReference (DHLR_FPARM1
  1370.     long far *fileRef,
  1371.     long far *flags)
  1372. {
  1373.     void far *storageH = instanceStorage;
  1374.     DataHInstanceStoragePtr storage;
  1375.     OSErr oserr = noErr;
  1376.  
  1377.     if ((fileRef == NULL) || (flags == NULL)) {
  1378.         return(paramErr);
  1379.     }
  1380.  
  1381.     // locate instance storage
  1382.     storage = (DataHInstanceStoragePtr)GlobalLock((HGLOBAL)LOWORD(storageH));
  1383.     if(storage == NULL)
  1384.         return(insufficientMemory);
  1385.  
  1386.     if (storage->mmioH != mmioINVALID) {
  1387.         *fileRef = (int)storage->mmioH;
  1388.         *flags = storage->lFlags;
  1389.     } else {
  1390.         oserr = invalidDataRef;
  1391.     }
  1392.     // done 
  1393.     GlobalUnlock((HGLOBAL)LOWORD(storageH));
  1394.     return(oserr);
  1395. }
  1396.